import datetime
import pymysql
import redis
from constant.constant import *
from globals.globals import *

equipments_sql = 'select ID from equipment'
with my_session() as session:
    equipments = session.execute(equipments_sql).fetchall()

pool = redis.ConnectionPool(host=constant.REDIS_HOST, port=constant.REDIS_PORT,password=constant.REDIS_PASSWORD, decode_responses=True)
r = redis.Redis(connection_pool=pool)

# 设备-子设备-AItag森林
equip_field_dict = {}
if not r.hget('data_equipment', 'sub_equip_tree'):
    for equip in equipments:
        sub_equip_sql = f'select sub_equipment from sub_equipment where equipmentID = {equip[0]}'
        with my_session() as session:
            sub_equips = session.execute(sub_equip_sql).fetchall()
            if not sub_equips:
                tag_sql = f'select tag_id from equipmenttag where equipmentID = {equip[0]} and lower_limit is not null;'
                tags = session.execute(tag_sql).fetchall()
                tag_list = []
                for tag in tags:
                    tag_list.append(tag[0])
                equip_field_dict[equip[0]] = tag_list
            else:
                equip_field_dict[equip[0]] = {}
                for sub_equip in sub_equips:
                    sub_equip_field_sql = f'select tag_id , tag_means from equipmenttag where equipmentID = {equip[0]} and sub_equipment = "{sub_equip[0]}"'
                    sub_equip_fields = session.execute(sub_equip_field_sql).fetchall()
                    sub_equip_field_dict = {}
                    for sub_equip_field in sub_equip_fields:
                        sub_equip_field_dict[sub_equip_field.tag_means] = sub_equip_field.tag_id
                    equip_field_dict[equip[0]][sub_equip[0]] = sub_equip_field_dict
    # 森林写入redis
    r.hset('data_equipment', 'sub_equip_tree', str(equip_field_dict))
sub_equip_tree = eval(r.hget('data_equipment', 'sub_equip_tree'))


class HealthIndexModel():
    '''设备健康度模型'''
    # 设备状态方法
    def equip_status(self, equipID):
        # 运行状态判断
        equip_status = r.hmget('data_equipment', [str(equipID) + '_running', str(equipID) + '_accident'])
        # 故障处理
        if equip_status[1] == '1':
            self.equip_health_create()
        # 正常运行
        elif equip_status[0] == '1' and equip_status[1] == None or equip_status[0] == '1' and equip_status[
            1] == '0':
            # 有部件
            if isinstance(sub_equip_tree[equipID], dict):
                self.sub_equip_status(equipID)
            # 无部件
            elif sub_equip_tree[equipID]:
                self.equip_health_index(equipID)
        # 停机处理
        elif equip_status[0] == '0' and equip_status[1] == None or equip_status[0] == '0' and equip_status[1] == '0':
            # 有部件
            if isinstance(sub_equip_tree[equipID], dict):
                self.sub_equip_status(equipID, status='stopping')
            # 无部件
            elif sub_equip_tree[equipID]:
                self.equip_health_index(equipID, status='stopping')
        # 无运行模型处理
        else:
            print(equipID ,'未给出运行模型')


    # 含部件设备健康度计算
    def sub_equip_status(self, equipID, status=None):
        score = 0
        accident = 0
        stopping = 0
        for sub_equip in sub_equip_tree[equipID].keys():
            # 故障处理
            if r.hget('data_equipment', str(equipID) + '_' + str(sub_equip) + '_accident') == '1':
                self.sub_equip_health_index(equipID=equipID, subEquip=sub_equip, status='accident')
                accident = 1
            # 无故障处理
            else:
                sql = f'select * from subequipmentrunmodel where equipmentID = {equipID} and sub_equipment = "{sub_equip}"'
                with my_session() as session:
                    sub_equip_run_model = session.execute(sql).fetchall()
                # 有运行模型处理
                if sub_equip_run_model:
                    ifcon = r.hget('data_realtime', sub_equip_run_model[0].ifconditions)
                    result = None
                    if ifcon:
                        result = operators[sub_equip_run_model[0].symbol](int(ifcon), int(sub_equip_run_model[0].standvalue))
                    # 运行处理
                    if result:
                        health_score = self.sub_equip_health_index(equipID=equipID, subEquip=sub_equip, status='running')
                        score += health_score
                    # 停机处理
                    else:
                        self.sub_equip_health_index(equipID=equipID, subEquip=sub_equip,
                                                                       status='stopping')
                        stopping += 1
                # 无运行模型处理
                else:
                    # 部件有tag点
                    if sub_equip_tree[equipID][sub_equip]:
                        health_score = self.sub_equip_health_index(equipID=equipID, subEquip=sub_equip,
                                                                   status='running')
                        score += health_score
        if accident:
            score = 0
        else:
            score = round(score / (len(sub_equip_tree[equipID].keys()) - stopping), 2)
        self.equip_health_create(equipmentID=equipID, score=score)


    # 无部件设备健康度计算
    def equip_health_index(self, equipID, status=None):
        if status:
            health_score = r.hget('data_equipment', str(equipID) + '_lastrun_score')
            if health_score:
                health_score = float(health_score)
                self.equip_health_create(equipmentID=equipID, score=health_score)
            else:
                sql = f'select * from equipmenttag where equipmentID = {equipID} and lower_limit is not null'
                with my_session() as session:
                    tag_models = session.execute(sql).fetchall()
                score = 0
                for tag_model in tag_models:
                    health_index = self.tag_health_index(tag_id=tag_model.tag_id, min=tag_model.lower_limit,
                                                         max=tag_model.upper_limit, standard=tag_model.standard_value)
                    # 生成tag点健康度记录
                    self.tag_health_create(equipmentID=equipID, tag_id=tag_model.tag_id,
                                           score=health_index)
                    score += health_index
                score = round(score / len(tag_models), 2)
                r.hset('data_equipment', str(equipID) + '_lastrun_score', score)
                self.equip_health_create(equipmentID=equipID, score=score)
        else:
            sql = f'select * from equipmenttag where equipmentID = {equipID} and lower_limit is not null'
            with my_session() as session:
                tag_models = session.execute(sql).fetchall()
            score = 0
            for tag_model in tag_models:
                health_index = self.tag_health_index(tag_id=tag_model.tag_id, min=tag_model.lower_limit,
                                                     max=tag_model.upper_limit, standard=tag_model.standard_value)
                # 生成tag点健康度记录
                self.tag_health_create(equipmentID=equipID, tag_id=tag_model.tag_id,
                                       score=health_index)
                score += health_index
            score = round(score / len(tag_models), 2)
            r.hset('data_equipment', str(equipID) + '_lastrun_score', score)
            self.equip_health_create(equipmentID=equipID, score=score)


    # 部件健康度计算
    def sub_equip_health_index(self, equipID=None, subEquip=None, status=None) -> float:
        if status == 'accident':
            self.sub_equip_health_create(equipmentID=equipID, sub_equipment=subEquip, score=0)
            return 0
        else:
            sql = f'select * from equipmenttag where equipmentID = {equipID} and sub_equipment = "{subEquip}" and lower_limit is not null'
            with my_session() as session:
                tag_models = session.execute(sql).fetchall()
            score = 0
            for tag_model in tag_models:
                # 计算tag点健康度
                health_index = self.tag_health_index(tag_id=tag_model.tag_id, min=tag_model.lower_limit, max=tag_model.upper_limit, standard=tag_model.standard_value)
                # 生成tag点健康度记录
                self.tag_health_create(equipmentID=equipID, sub_equipment=subEquip, tag_id=tag_model.tag_id, score=health_index)
                score += health_index
            score = round(score / len(tag_models), 2)
            # 生成部件健康度记录
            self.sub_equip_health_create(equipmentID=equipID, sub_equipment=subEquip, score=score)
            return score


    # tag点健康度计算
    def tag_health_index(self, tag_id=None, min=None, max=None, standard=None) -> float:
        value_now = int(r.hget('data_realtime', tag_id))
        health_index = None
        if value_now >= min and value_now <= standard:
            health_index = (value_now - min) / (standard - min)
        elif value_now >= standard and value_now <= max:
            health_index = (max - value_now) / (max - standard)
        elif value_now < min or value_now > max:
            health_index = 0
        return round(health_index,2)


    # 生成tag点健康度评分信息
    def tag_health_create(self, equipmentID=None, sub_equipment=None, tag_id=None, score=None) -> None:
        start_time = datetime.datetime.now()
        sql = f'insert into health_rate_tag set ' \
              f'equipmentID={equipmentID}, ' \
              f'sub_equipment="{sub_equipment}",' \
              f'tag_id="{tag_id}",' \
              f'health_score="{score}",' \
              f'count_time="{start_time.strftime("%Y-%m-%d %H:%M")}",' \
              f'count_year="{start_time.strftime("%Y")}",' \
              f'count_month="{start_time.strftime("%Y-%m")}",' \
              f'count_day="{start_time.strftime("%Y-%m-%d")}",' \
              f'count_hour="{start_time.strftime("%Y-%m-%d %H")}";'
        with my_session() as session:
            session.execute(sql)


    # 生成部件健康度评分信息
    def sub_equip_health_create(self, equipmentID=None, sub_equipment=None, score=None) -> None:
        start_time = datetime.datetime.now()
        sql = f'insert into health_rate_sub_equipment set ' \
              f'equipmentID={equipmentID}, ' \
              f'sub_equipment="{sub_equipment}",' \
              f'health_score="{score}",' \
              f'count_time="{start_time.strftime("%Y-%m-%d %H:%M")}",' \
              f'count_year="{start_time.strftime("%Y")}",' \
              f'count_month="{start_time.strftime("%Y-%m")}",' \
              f'count_day="{start_time.strftime("%Y-%m-%d")}",' \
              f'count_hour="{start_time.strftime("%Y-%m-%d %H")}";'
        with my_session() as session:
            session.execute(sql)


    # 生成设备健康度评分信息
    def equip_health_create(self, equipmentID=None, score=None) -> None:
        start_time = datetime.datetime.now()
        sql = f'insert into health_rate_equipment set ' \
              f'equipmentID={equipmentID},' \
              f'health_score={score},' \
              f'count_time="{start_time.strftime("%Y-%m-%d %H:%M")}",' \
              f'count_year="{start_time.strftime("%Y")}",' \
              f'count_month="{start_time.strftime("%Y-%m")}",' \
              f'count_day="{start_time.strftime("%Y-%m-%d")}",' \
              f'count_hour="{start_time.strftime("%Y-%m-%d %H")}";'
        with my_session() as session:
            session.execute(sql)


def health_job():
    for equipID in equipments:
        HealthIndexModel().equip_status(equipID.ID)

